using System;
using System.Collections.Generic;
using System.Linq;
using Serialization;
using WindowsPhoneEssentials.Abstractions;
using WindowsPhoneEssentials.Diagnostics;
using WindowsPhoneMVC.Interfaces;
using WindowsPhoneMVC.Navigation;

namespace WindowsPhoneMVC
{
    internal class Journal : IJournal
    {
        internal const string JournalKeyPattern = "NavigationJournalFor{0}";

        public string NavigationFrameName { get; set; }

        private readonly List<NavigationRequest> historyRequests;
        private IDictionary<string, object> transientStore;

        internal Journal(string navigationFrameName)
        {
            historyRequests = new List<NavigationRequest>();
            NavigationFrameName = navigationFrameName;
        }

        public void Initialise(IPhoneApplicationService phoneApplicationService)
        {
            transientStore = phoneApplicationService.State;
            if (!transientStore.ContainsKey(JournalKey)) return;

            var history = SilverlightSerializer.Deserialize<List<NavigationRequest>>((byte[])transientStore[JournalKey]);
            if (history != null)
            {
                Trace.WriteDebug(this, () => string.Format("Journal loaded {0} requests from Isolated Storage", history.Count));
                historyRequests.AddRange(history);
            }
        }

        public NavigationRequest PopEntry()
        {
            var lastElement = historyRequests.LastOrDefault();
            if (lastElement != null)
            {
                Trace.WriteDebug(this, () => string.Format("{0}.{1} popped from Journal", lastElement.ControllerName, lastElement.ActionName));
                historyRequests.RemoveAt(historyRequests.Count - 1);
            }
            else 
                return null;

            return lastElement;
        }

        private string JournalKey
        {
            get { return string.Format(JournalKeyPattern, NavigationFrameName); }
        }

        public void PushEntry(NavigationRequest request)
        {
            Trace.WriteDebug(this, ()=> string.Format("{0}.{1} added to Journal", request.ControllerName, request.ActionName));
            historyRequests.Add(request);
        }

        public void Flush()
        {
            Trace.WriteDebug(this, () => "Flushing Journal to Isolated Storage");
            transientStore[JournalKey] = SilverlightSerializer.Serialize(historyRequests);
        }

        public bool IsEmpty()
        {
            return historyRequests.Count == 0;
        }
    }
}